#if defined(ARCTIC)
#if (FEATURE_MODE == 0)
#include "sal.h"
#include "ctc_error.h"
#include "sys_usw_common.h"
#include "sys_usw_chip.h"
#include "sys_usw_aps.h"
#include "drv_api.h"

int32
_sys_at_aps_set_hw(uint8 lchip, uint16 group_id, sys_dsaps_t* p_dsaps)
{
    uint32 cmd = 0;
    int32 ret = CTC_E_NONE;
    DsIpeApsBridge_m ds0;
    DsEpeApsBridge_m ds1;
    DsMetApsBridge_m ds2;
    DsOamApsBridge_m ds3;

    sal_memset(&ds0, 0, sizeof(ds0));
    sal_memset(&ds1, 0, sizeof(ds1));
    sal_memset(&ds2, 0, sizeof(ds2));
    sal_memset(&ds3, 0, sizeof(ds3));
    DRV_SET_FLD(V, DsIpeApsBridge, differentNexthop_f           , &ds0, p_dsaps->different_nhp);
    DRV_SET_FLD(V, DsIpeApsBridge, l2ApsMode_f                  , &ds0, p_dsaps->l2_aps_mode);
    DRV_SET_FLD(V, DsIpeApsBridge, protectingNextApsBridgeEn_f  , &ds0, p_dsaps->p_next_aps_brg_en);
    DRV_SET_FLD(V, DsIpeApsBridge, workingNextApsBridgeEn_f     , &ds0, p_dsaps->w_next_aps_brg_en);
    DRV_SET_FLD(V, DsIpeApsBridge, protectingDestMap_f          , &ds0, p_dsaps->p_dest_map);
    DRV_SET_FLD(V, DsIpeApsBridge, protectingNextHopPtr_f       , &ds0, p_dsaps->p_nhp_ptr);
    DRV_SET_FLD(V, DsIpeApsBridge, protectingServiceId_f        , &ds0, p_dsaps->p_service_id);
    DRV_SET_FLD(V, DsIpeApsBridge, workingDestMap_f             , &ds0, p_dsaps->w_dest_map);
    DRV_SET_FLD(V, DsIpeApsBridge, workingNextHopPtr_f          , &ds0, p_dsaps->w_nhp_ptr);
    DRV_SET_FLD(V, DsIpeApsBridge, workingServiceId_f           , &ds0, p_dsaps->w_service_id);
    DRV_SET_FLD(V, DsIpeApsBridge, protectingSr6NextSidEn_f     , &ds0, p_dsaps->p_sr6_next_sid_en);
    DRV_SET_FLD(V, DsIpeApsBridge, workingBypassIngressEdit_f   , &ds0, p_dsaps->w_bypass_ingress_edit);
    DRV_SET_FLD(V, DsIpeApsBridge, protectingBypassIngressEdit_f, &ds0, p_dsaps->p_bypass_ingress_edit);

    DRV_SET_FLD(V, DsEpeApsBridge, spmeApsEn_f                  , &ds1, p_dsaps->spme_aps_en);
    DRV_SET_FLD(V, DsEpeApsBridge, protectingNextApsBridgeEn_f  , &ds1, p_dsaps->p_next_aps_brg_en);
    DRV_SET_FLD(V, DsEpeApsBridge, protectingOuterEditLocation_f, &ds1, p_dsaps->p_outer_edit_location);
    DRV_SET_FLD(V, DsEpeApsBridge, protectingOuterEditPtrType_f , &ds1, p_dsaps->p_outer_edit_ptr_type);
    DRV_SET_FLD(V, DsEpeApsBridge, workingNextApsBridgeEn_f     , &ds1, p_dsaps->w_next_aps_brg_en);
    DRV_SET_FLD(V, DsEpeApsBridge, workingOuterEditLocation_f   , &ds1, p_dsaps->w_outer_edit_location);
    DRV_SET_FLD(V, DsEpeApsBridge, workingOuterEditPtrType_f    , &ds1, p_dsaps->w_outer_edit_ptr_type);
    DRV_SET_FLD(V, DsEpeApsBridge, protectingDestMap_f          , &ds1, p_dsaps->p_dest_map);
    DRV_SET_FLD(V, DsEpeApsBridge, protectingDestVlanPtr_f      , &ds1, p_dsaps->p_dest_vlan_ptr);
    DRV_SET_FLD(V, DsEpeApsBridge, protectingOuterEditPtr_f     , &ds1, p_dsaps->p_outer_edit_ptr);
    DRV_SET_FLD(V, DsEpeApsBridge, workingDestMap_f             , &ds1, p_dsaps->w_dest_map);
    DRV_SET_FLD(V, DsEpeApsBridge, workingDestVlanPtr_f         , &ds1, p_dsaps->w_dest_vlan_ptr);
    DRV_SET_FLD(V, DsEpeApsBridge, workingOuterEditPtr_f        , &ds1, p_dsaps->w_outer_edit_ptr);

    DRV_SET_FLD(V, DsMetApsBridge, differentNexthop_f           , &ds2, p_dsaps->different_nhp);
    DRV_SET_FLD(V, DsMetApsBridge, l2ApsMode_f                  , &ds2, p_dsaps->l2_aps_mode);
    DRV_SET_FLD(V, DsMetApsBridge, protectingEndLocalRep_f      , &ds2, p_dsaps->p_end_local_rep);
    DRV_SET_FLD(V, DsMetApsBridge, protectingIsLinkAggregation_f, &ds2, p_dsaps->p_is_agg);
    DRV_SET_FLD(V, DsMetApsBridge, protectingNextApsBridgeEn_f  , &ds2, p_dsaps->p_next_aps_brg_en);
    DRV_SET_FLD(V, DsMetApsBridge, protectingRemoteChip_f       , &ds2, p_dsaps->p_remote_chip);
    DRV_SET_FLD(V, DsMetApsBridge, workingIsLinkAggregation_f   , &ds2, p_dsaps->w_is_link_agg);
    DRV_SET_FLD(V, DsMetApsBridge, workingNextApsBridgeEn_f     , &ds2, p_dsaps->w_next_aps_brg_en);
    DRV_SET_FLD(V, DsMetApsBridge, workingRemoteChip_f          , &ds2, p_dsaps->w_remote_chip);
    DRV_SET_FLD(V, DsMetApsBridge, protectingDestMap_f          , &ds2, p_dsaps->p_dest_map);
    DRV_SET_FLD(V, DsMetApsBridge, protectingNextHopPtr_f       , &ds2, p_dsaps->p_nhp_ptr);
    DRV_SET_FLD(V, DsMetApsBridge, protectingServiceId_f        , &ds2, p_dsaps->p_service_id);
    DRV_SET_FLD(V, DsMetApsBridge, workingDestMap_f             , &ds2, p_dsaps->w_dest_map);
    DRV_SET_FLD(V, DsMetApsBridge, workingEndLocalRep_f         , &ds2, p_dsaps->w_end_local_rep);
    DRV_SET_FLD(V, DsMetApsBridge, workingNextHopPtr_f          , &ds2, p_dsaps->w_nhp_ptr);
    DRV_SET_FLD(V, DsMetApsBridge, workingServiceId_f           , &ds2, p_dsaps->w_service_id);

    DRV_SET_FLD(V, DsOamApsBridge, protectingNextApsBridgeEn_f  , &ds3, p_dsaps->p_next_aps_brg_en);
    DRV_SET_FLD(V, DsOamApsBridge, workingNextApsBridgeEn_f     , &ds3, p_dsaps->w_next_aps_brg_en);
    DRV_SET_FLD(V, DsOamApsBridge, protectingDestMap_f          , &ds3, p_dsaps->p_dest_map);
    DRV_SET_FLD(V, DsOamApsBridge, workingDestMap_f             , &ds3, p_dsaps->w_dest_map);
    DRV_SET_FLD(V, DsOamApsBridge, protectingSr6NextSidEn_f     , &ds3, p_dsaps->p_sr6_next_sid_en);

    cmd = DRV_IOW(DsIpeApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds0));
    cmd = DRV_IOW(DsEpeApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds1));
    cmd = DRV_IOW(DsMetApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds2));
    cmd = DRV_IOW(DsOamApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds3));

    return ret;
}

int32
_sys_at_aps_get_hw(uint8 lchip, uint16 group_id, sys_dsaps_t* p_dsaps)
{
    uint32 cmd = 0;
    DsIpeApsBridge_m ds0;
    DsEpeApsBridge_m ds1;
    DsMetApsBridge_m ds2;

    cmd = DRV_IOR(DsIpeApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds0));
    cmd = DRV_IOR(DsEpeApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds1));
    cmd = DRV_IOR(DsMetApsBridge_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, cmd, &ds2));

    p_dsaps->different_nhp              =  DRV_GET_FLD(V, DsIpeApsBridge, differentNexthop_f           , &ds0);
    p_dsaps->l2_aps_mode                =  DRV_GET_FLD(V, DsIpeApsBridge, l2ApsMode_f                  , &ds0);
    p_dsaps->p_next_aps_brg_en       =  DRV_GET_FLD(V, DsIpeApsBridge, protectingNextApsBridgeEn_f  , &ds0);
    p_dsaps->w_next_aps_brg_en          =  DRV_GET_FLD(V, DsIpeApsBridge, workingNextApsBridgeEn_f     , &ds0);
    p_dsaps->p_dest_map              =  DRV_GET_FLD(V, DsIpeApsBridge, protectingDestMap_f          , &ds0);
    p_dsaps->p_nhp_ptr               =  DRV_GET_FLD(V, DsIpeApsBridge, protectingNextHopPtr_f       , &ds0);
    p_dsaps->p_service_id            =  DRV_GET_FLD(V, DsIpeApsBridge, protectingServiceId_f        , &ds0);
    p_dsaps->w_dest_map                 =  DRV_GET_FLD(V, DsIpeApsBridge, workingDestMap_f             , &ds0);
    p_dsaps->w_nhp_ptr                  =  DRV_GET_FLD(V, DsIpeApsBridge, workingNextHopPtr_f          , &ds0);
    p_dsaps->w_service_id               =  DRV_GET_FLD(V, DsIpeApsBridge, workingServiceId_f           , &ds0);
    p_dsaps->p_sr6_next_sid_en       =  DRV_GET_FLD(V, DsIpeApsBridge, protectingSr6NextSidEn_f     , &ds0);
    p_dsaps->w_bypass_ingress_edit      =  DRV_GET_FLD(V, DsIpeApsBridge, workingBypassIngressEdit_f   , &ds0);
    p_dsaps->p_bypass_ingress_edit   =  DRV_GET_FLD(V, DsIpeApsBridge, protectingBypassIngressEdit_f, &ds0);

    p_dsaps->spme_aps_en                =  DRV_GET_FLD(V, DsEpeApsBridge, spmeApsEn_f                  , &ds1);
    p_dsaps->p_outer_edit_location   =  DRV_GET_FLD(V, DsEpeApsBridge, protectingOuterEditLocation_f, &ds1);
    p_dsaps->p_outer_edit_ptr_type   =  DRV_GET_FLD(V, DsEpeApsBridge, protectingOuterEditPtrType_f , &ds1);
    p_dsaps->w_outer_edit_location      =  DRV_GET_FLD(V, DsEpeApsBridge, workingOuterEditLocation_f   , &ds1);
    p_dsaps->w_outer_edit_ptr_type      =  DRV_GET_FLD(V, DsEpeApsBridge, workingOuterEditPtrType_f    , &ds1);
    p_dsaps->p_dest_vlan_ptr         =  DRV_GET_FLD(V, DsEpeApsBridge, protectingDestVlanPtr_f      , &ds1);
    p_dsaps->p_outer_edit_ptr        =  DRV_GET_FLD(V, DsEpeApsBridge, protectingOuterEditPtr_f     , &ds1);
    p_dsaps->w_dest_vlan_ptr            =  DRV_GET_FLD(V, DsEpeApsBridge, workingDestVlanPtr_f         , &ds1);
    p_dsaps->w_outer_edit_ptr           =  DRV_GET_FLD(V, DsEpeApsBridge, workingOuterEditPtr_f        , &ds1);

    p_dsaps->p_end_local_rep         =  DRV_GET_FLD(V, DsMetApsBridge, protectingEndLocalRep_f      , &ds2);
    p_dsaps->p_is_agg               =  DRV_GET_FLD(V, DsMetApsBridge, protectingIsLinkAggregation_f, &ds2);
    p_dsaps->p_remote_chip           =  DRV_GET_FLD(V, DsMetApsBridge, protectingRemoteChip_f       , &ds2);
    p_dsaps->w_is_link_agg              =  DRV_GET_FLD(V, DsMetApsBridge, workingIsLinkAggregation_f   , &ds2);
    p_dsaps->w_remote_chip              =  DRV_GET_FLD(V, DsMetApsBridge, workingRemoteChip_f          , &ds2);
    p_dsaps->w_end_local_rep            =  DRV_GET_FLD(V, DsMetApsBridge, workingEndLocalRep_f         , &ds2);

    return CTC_E_NONE;
}

int32
_sys_at_aps_set_protections(uint8 lchip, void* p_grp_bitmap)
{

#define APS_PROTECTION_NUM 64
    uint32 protectingEn[2] = {0};
    ctc_aps_grp_bitmap_t* grp_bitmap = (ctc_aps_grp_bitmap_t*)p_grp_bitmap;
    uint32* bitmap =NULL;
    uint32* mask =NULL;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 i = 0;
    uint8 grp_base = 0;
    uint8 tmp_array_num=0;

    SYS_APS_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    grp_base = grp_bitmap->grp_base;
    if (grp_base % CTC_CONST64 || (grp_base + CTC_CONST64*grp_bitmap->array_num) > MCHIP_CAP(SYS_CAP_APS_GROUP_NUM))
    {
        return CTC_E_INVALID_CONFIG;
    }

    bitmap = mem_malloc(MEM_APS_MODULE, MCHIP_CAP(SYS_CAP_APS_GROUP_NUM)/8);
    mask = mem_malloc(MEM_APS_MODULE,  MCHIP_CAP(SYS_CAP_APS_GROUP_NUM)/8);
    sal_memset(bitmap,0,MCHIP_CAP(SYS_CAP_APS_GROUP_NUM)/8);
    sal_memset(mask, 0, MCHIP_CAP(SYS_CAP_APS_GROUP_NUM)/8);

    tmp_array_num = grp_bitmap->array_num*2 + grp_base / 32 + !!(grp_base % 32);
    tmp_array_num += (tmp_array_num&0x1);

    sal_memcpy((uint8*)bitmap + grp_base / CTC_CONST8, grp_bitmap->bitmap, sizeof(uint64)*grp_bitmap->array_num);
    sal_memcpy((uint8*)mask + grp_base / CTC_CONST8, grp_bitmap->bitmap_mask, sizeof(uint64)*grp_bitmap->array_num);
    
    for (i = 0; i < tmp_array_num/2; i++)
    {
        cmd = DRV_IOR(DsIpeApsProtectionEn_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, i , cmd, &protectingEn);         
        protectingEn[0] = (protectingEn[0]&(~mask[2*i])) | (bitmap[2*i] & mask[2*i]);
        protectingEn[1] = (protectingEn[1]&(~mask[2*i + 1])) | (bitmap[2*i + 1] & mask[2*i + 1]);
        cmd = DRV_IOW(DsIpeApsProtectionEn_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, i, cmd, &protectingEn);
        cmd = DRV_IOW(DsEpeApsProtectionEn_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, i, cmd, &protectingEn);
        cmd = DRV_IOW(DsMetApsProtectionEn_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, i, cmd, &protectingEn);
        cmd = DRV_IOW(DsOamApsProtectionEn_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, i, cmd, &protectingEn);
    }        
    mem_free(bitmap);
    mem_free(mask);


    return ret;

}


#endif
#endif

